import logging
import os
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from pathlib import Path
from typing import List, Optional, Union

import aiosmtplib
import jinja2

from app.core.config import settings

logger = logging.getLogger(__name__)


class EmailHelper:
    def __init__(
        self,
        host: str = settings.SMTP_HOST,
        port: int = settings.SMTP_PORT,
        username: str = settings.SMTP_USERNAME,
        password: str = settings.SMTP_PASSWORD,
        use_tls: bool = settings.SMTP_TLS,
        default_from_email: str = settings.DEFAULT_FROM_EMAIL,
        template_dir: str = "templates/email",
    ):
        self.host = host
        self.port = port
        self.username = username
        self.password = password
        self.use_tls = use_tls
        self.default_from_email = default_from_email

        # 设置模板环境
        template_path = Path(settings.BASE_DIR) / template_dir
        self.template_env = jinja2.Environment(
            loader=jinja2.FileSystemLoader(str(template_path)),
            autoescape=True,
            trim_blocks=True,
            lstrip_blocks=True,
        )

        # 添加自定义过滤器
        self.template_env.filters.update(
            {
                "datetime": lambda dt: dt.strftime("%Y-%m-%d %H:%M:%S"),
                "date": lambda dt: dt.strftime("%Y-%m-%d"),
            }
        )

    async def send_email(
        self,
        subject: str,
        recipients: List[str],
        body: str,
        html: Optional[str] = None,
        sender: Optional[str] = None,
        cc: Optional[List[str]] = None,
        bcc: Optional[List[str]] = None,
    ) -> bool:
        if not recipients:
            return False

        message = MIMEMultipart("alternative")
        message["Subject"] = subject
        message["From"] = sender or self.default_from_email
        message["To"] = ", ".join(recipients)

        if cc:
            message["Cc"] = ", ".join(cc)
        if bcc:
            message["Bcc"] = ", ".join(bcc)

        # 添加纯文本内容
        message.attach(MIMEText(body, "plain"))

        # 如果提供了HTML内容，也添加HTML版本
        if html:
            message.attach(MIMEText(html, "html"))

        try:
            smtp = aiosmtplib.SMTP(
                hostname=self.host,
                port=self.port,
                use_tls=self.use_tls,
            )
            await smtp.connect()
            if self.username and self.password:
                await smtp.login(self.username, self.password)

            all_recipients = recipients + (cc or []) + (bcc or [])
            await smtp.send_message(message, self.default_from_email, all_recipients)
            await smtp.quit()
            return True
        except Exception as e:
            # TODO: 添加日志记录
            logger.error(f"发送邮件失败: {str(e)}")
            return False

    def _render_template(self, template_name: str, context: dict) -> tuple[str, str]:
        """渲染邮件模板，返回纯文本和HTML版本"""
        try:
            # 加载HTML模板
            html_template = self.template_env.get_template(f"{template_name}.html")
            html_content = html_template.render(**context)

            # 尝试加载纯文本模板，如果不存在则使用HTML转文本
            try:
                text_template = self.template_env.get_template(f"{template_name}.txt")
                text_content = text_template.render(**context)
            except jinja2.TemplateNotFound:
                # 简单移除HTML标签作为纯文本内容
                from bs4 import BeautifulSoup

                text_content = BeautifulSoup(html_content, "html.parser").get_text()

            return text_content, html_content
        except jinja2.TemplateNotFound as e:
            logger.error(f"邮件模板 {template_name} 不存在")
            raise ValueError(f"邮件模板 {template_name} 不存在") from e
        except Exception as e:
            logger.error(f"渲染邮件模板失败: {str(e)}")
            raise ValueError(f"渲染邮件模板失败: {str(e)}") from e

    async def send_template_email(
        self,
        subject: str,
        recipients: Union[str, List[str]],
        template_name: str,
        context: dict,
        sender: Optional[str] = None,
        cc: Optional[List[str]] = None,
        bcc: Optional[List[str]] = None,
    ) -> bool:
        if isinstance(recipients, str):
            recipients = [recipients]

        # 渲染模板
        try:
            text_content, html_content = self._render_template(template_name, context)
        except ValueError as e:
            logger.error(f"模板渲染失败: {str(e)}")
            return False

        return await self.send_email(
            subject=subject,
            recipients=recipients,
            body=text_content,
            html=html_content,
            sender=sender,
            cc=cc,
            bcc=bcc,
        )


# 创建全局邮件助手实例
email_helper = EmailHelper()
